﻿///////////////////////////////////////////////////////////////////////////////
// File:        ServerThread.hpp
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#ifndef NIO_NET_SERVERTHREAD_HPP_
#define NIO_NET_SERVERTHREAD_HPP_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <nio/base/Thread.hpp>
#include <nio/net/EventLoop.hpp>
#include <nio/net/Connection.hpp>

namespace nio
{
    namespace net
    {
        class ServerThread : public base::Thread
        {
        public:
            struct Statics
            {
                int connLoad;
                base::time_t frameUseTime;
            };

        public:
            ServerThread(void);
            virtual ~ServerThread(void);

        public:
            virtual void run(void);
            virtual void stop(void);

        public:
            EventLoop& getLoop(void) { return eventLoop_; }
            void addConnection(ConnectionPtr& conn);
            void setAddConnectionFN(boost::function<void(ConnectionPtr&)> fn) { addConnectionFN_ = fn; }
            void setRemoveConnectionFN(boost::function<void(Connection*)> fn) { removeConnectionFN_ = fn; }
            int getLoad(void) const { return connLoad_; }

            void getStatics(struct Statics& statics)
            {
                statics.connLoad = connLoad_;
                statics.frameUseTime = eventLoop_.getFrameUseTime();
            }

        private:
            void incLoad(void)
            {
#if defined(__WINDOWS__)
                ::InterlockedIncrement((LONG *)&connLoad_);
#elif defined(__LINUX__)
                ::__sync_add_and_fetch(&connLoad_, 1);
#endif
            }

            void decLoad(void)
            {
#if defined(__WINDOWS__)
                ::InterlockedDecrement((LONG*)&connLoad_);
#elif defined(__LINUX__)
                ::__sync_sub_and_fetch(&connLoad_, 1);
#endif
            }

        private:
            void doAddConnection(ConnectionPtr& conn);
            void shutdownConnection(Connection* conn);
            void doShutdownConnection(Connection* conn);

        private:
            int                                     connLoad_;
            EventLoop                               eventLoop_;

            boost::function<void(ConnectionPtr&)>   addConnectionFN_;
            boost::function<void(Connection*)>      removeConnectionFN_;
        };

        typedef boost::shared_ptr<ServerThread> ServerThreadPtr;
    }
}

#endif //NIO_NET_SERVERTHREAD_HPP_
